package com.cs.pk.view.tab;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MenuDetectEvent;
import org.eclipse.swt.events.MenuDetectListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;

import com.cs.pk.utils.FontUtil;
import com.sshtools.j2ssh.SshClient;
import com.sshtools.j2ssh.authentication.AuthenticationProtocolState;
import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
import com.sshtools.j2ssh.configuration.ConfigurationLoader;
import com.sshtools.j2ssh.configuration.SshConnectionProperties;
import com.sshtools.j2ssh.connection.ChannelState;
import com.sshtools.j2ssh.io.IOStreamConnector;
import com.sshtools.j2ssh.session.SessionChannelClient;
import com.sshtools.j2ssh.transport.IgnoreHostKeyVerification;

public class StyleTextTab extends StyledText implements KeyListener,
		MenuDetectListener, VerifyKeyListener {

	private Font txtFont = null;

	public StyleTextTab(Composite parent) {
		super(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
		addKeyListener(this);
		addMenuDetectListener(this);
		addVerifyKeyListener(this);
		txtFont = FontUtil.adjustFont(this, 10, SWT.NORMAL);
		setFont(txtFont);
		pis = new PipedInputStream();
		try {
			pos = new PipedOutputStream(pis);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	// private java.util.List ranges = new java.util.ArrayList();

	IAction cut = new Action("Cut") {
		public void run() {
			cut();
		}

	};

	IAction copy = new Action("Copy") {

		public void run() {
			copy();
		}

	};

	IAction paste = new Action("Paste") {
		public void run() {
			paste();
		}

	};

	public IAction[] getShellActions() {
		return new IAction[] { cut, copy, paste };
	}

	private void createAndShowPopupMenu(MenuDetectEvent mEvent) {
		Menu menu = new Menu(getShell(), SWT.POP_UP);
		IAction actions[] = getShellActions();
		for (int i = 0; i < actions.length; i++) {
			MenuItem item = new MenuItem(menu, SWT.PUSH);
			item.setText(actions[i].getText());
			item.setData(actions[i]);
			item.addListener(SWT.Selection, new Listener() {
				public void handleEvent(Event e) {
					MenuItem i = (MenuItem) e.widget;
					((IAction) i.getData()).run();
				}
			});
		}

		menu.setLocation(mEvent.x, mEvent.y);
		menu.setVisible(true);
		while (!menu.isDisposed() && menu.isVisible()) {
			if (!getShell().getDisplay().readAndDispatch())
				getShell().getDisplay().sleep();
		}
		menu.dispose();
	}

	public void keyPressed(KeyEvent e) {
		// System.out.println("prabhatk: StyleTextTab.keyPressed()");
		// System.out.println("prabhatk: StyleTextTab.keyPressed() "+e.character+" "+e.keyCode+" "+e.stateMask);
		if (e.stateMask != 262144 && e.keyCode != 131072
				&& e.keyCode != 16777298 && e.keyCode != 65536) {// Not a CTR
																	// mask
			if (backSpaceAndDelete(e, getCaretOffset())) {
				updateCache(new char[] { e.character });
			}
		}
	}

	private boolean backSpaceAndDelete(KeyEvent e, int position) {
		// if(position==0 && keyCode == 8 ) {
		// return false;
		// }
//System.out.println("StyleTextTab.backSpaceAndDelete() "+" cc.length = "+cc.length+" position = "+position);
		if (e.keyCode == 8 || e.keyCode == 127) {// Backspace or Del

			if (cc.length > 0) {
			        int _len ;
			        if(position-1<=0){
			            _len=0;
			        }else{
				String text = getText(0, position-1);
				String tokens[] = text.split("\r?\n");
				String lastToken = tokens[tokens.length - 1];
				_len = getLineCount()==tokens.length?lastToken.length():0;
//				System.out.println("prabhatk:  last token length "
//					+ lastToken.length()+" noofline="+getLineCount());
			        }
				
			       
				char temp[] = new char[cc.length - 1];
				
//				System.out
//						.println("prabhatk: StyleTextTab.backSpaceAndDelete() temp.length = "
//								+ temp.length
//								+ " position = "
//								+ position
//								+ " cc.length" + cc.length);
				System.arraycopy(cc, 0, temp, 0, /*_len>cc.length?(cc.length-1):*/_len);
				if (_len+1 < cc.length) {// end
					System.arraycopy(cc, _len + 1, temp, _len,
							cc.length - (_len + 1));
				}
				cc = temp;
				updateText(position - 1);
			} else {
				e.doit = false;
			}
			return false;
		}
		updateText(position - 1);
		return true;
	}

	private void updateText(int start) {
		if (start >= 0) {
			replaceStyleRanges(start, 1, new StyleRange[] { new StyleRange(
					start, 1,
					this.getDisplay().getSystemColor(SWT.COLOR_GREEN), null,
					SWT.NORMAL) });
		}
	}

	private void write(String value) {
		try {
			pos.write(value.getBytes());
			// if(e.character =='\n') {
			pos.flush();
			// }
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}

	private void updateCache(String values) {
		updateCache(values.toCharArray());
	}

	private char[] cc = new char[0];

	private void updateCache(char[] c) {
		char temp[] = null;
		// System.arraycopy(temp, 0, cc, 0, cc.length-1);
		for (int i = 0; i < c.length; i++) {
			// System.out.print(c[i]);
			if (c[i] == '\n' || c[i] == '\r') {
				temp = new char[cc.length + i + 1];
				System.arraycopy(cc, 0, temp, 0, cc.length);
				// System.out.println(temp);
				System.arraycopy(c, 0, temp, cc.length, i + 1);
				// System.out.println(temp);
				write(new String(temp));
				cc = new char[0];
				temp = new char[c.length - (i + 1)];
				System.arraycopy(c, i + 1, temp, 0, c.length - (i + 1));
				// System.out.println(temp);
				updateCache(temp);
				return;
			}
		}
		temp = new char[cc.length + c.length];
		System.arraycopy(cc, 0, temp, 0, cc.length);
		System.arraycopy(c, 0, temp, cc.length, c.length);
		cc = temp;
	}

	public void keyReleased(KeyEvent e) {

	}

	static int c = 0;

	public static void main(String[] args) {
		final Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setLayout(new FillLayout(SWT.VERTICAL));
		final StyleTextTab styledText = new StyleTextTab(shell);

		Button b = new Button(shell, SWT.PUSH);
		b.setText("Write");
		b.addSelectionListener(new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {

			}

			public void widgetSelected(SelectionEvent e) {
				// styledText.append(""+c++);
				// styledText.getDisplay().asyncExec(new Runnable() {
				//
				// public void run() {
				//
				// // Job sshJob = new Job("build") {
				// //
				// // protected IStatus run(IProgressMonitor monitor) {
				// // styledText.creatSSHConnection();
				// // return Status.OK_STATUS;
				// // }
				// //
				// // };
				// // sshJob.schedule();
				// // styledText.setEditable(true);
				// }
				//
				// });
				Job sshJob = new Job("build") {

					protected IStatus run(IProgressMonitor monitor) {
						styledText.creatSSHConnection();
						return Status.OK_STATUS;
					}

				};
				sshJob.schedule();
				// Thread t = new Thread() {
				// public void run() {
				//						
				// }
				// };
				// t.start();

			}

		});
		styledText.setBounds(10, 10, 500, 100);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		display.dispose();

	}

	public void paste() {
		int start = getCaretOffset();
		super.paste();

		int length = getCaretOffset() - start;
		replaceStyleRanges(start, length, new StyleRange[] { new StyleRange(
				start, length, this.getDisplay()
						.getSystemColor(SWT.COLOR_GREEN), null, SWT.NORMAL) });
		String pasteString = getText(start, start + length - 1);
		updateCache(pasteString);
		// String tokens[] = pasteString.split("\n");
		// Pattern p = Pattern.compile("\n");
		// Matcher m = p.matcher(pasteString);
		// int count = 0;
		// while(m.find()) {
		// count++;
		// }
		// System.out.println("prabhatk: StyleTextTab.paste() "+count);
		// boolean flag = false;
		// if(tokens.length == count) {
		// System.out.println("prabhatk: StyleTextTab.paste() last line has \n");
		// flag = true;
		// }
		// for (int i = 0; i < tokens.length; i++) {
		//			
		// if(i==tokens.length-1&&flag) {
		// pos.flush();
		// }
		// }
		//		

		// try {
		// pos.write(pasteString.getBytes());
		// pos.flush();
		// } catch (IOException e) {
		// e.printStackTrace();
		// }
	}

	public void menuDetected(MenuDetectEvent e) {
		createAndShowPopupMenu(e);
	}

	public void dispose() {
		txtFont.dispose();
		txtFont = null;
		super.dispose();
	}

	PipedInputStream pis = null;
	PipedOutputStream pos = null;

	private void creatSSHConnection() {
		try {
			// JDK > 1.4 ONLY
			/*
			 * Handler fh = new FileHandler("example.log"); fh.setFormatter(new
			 * SimpleFormatter());
			 * Logger.getLogger("com.sshtools").setUseParentHandlers(false);
			 * Logger.getLogger("com.sshtools").addHandler(fh);
			 * Logger.getLogger("com.sshtools").setLevel(Level.ALL);
			 */
			// Configure J2SSH (This will attempt to install the bouncycastle
			// provider
			// under jdk 1.3.1)
			ConfigurationLoader.initialize(false);

			BufferedReader reader = new BufferedReader(new InputStreamReader(
					pis));
			System.out.print("Connect to host? ");
			String hostname = /* "sdf.lonestar.org"; */reader.readLine();
			// Make a client connection
			SshClient ssh = new SshClient();
			ssh.setSocketTimeout(30000);
			SshConnectionProperties properties = new SshConnectionProperties();
			properties.setHost(hostname);
			// properties.setPrefPublicKey("ssh-dss");
			// properties.setPrefPublicKey("ssh-rsa");
			properties.setForwardingAutoStartMode(true);
			// Connect to the host
			ssh.setUseDefaultForwarding(true);
			ssh.connect(properties, new IgnoreHostKeyVerification());
			// Create a password authentication instance
			PasswordAuthenticationClient pwd = new PasswordAuthenticationClient();
			// Get the users name
			System.out.print("Username? ");
			// Read the password
			String username = /* "prabhat"; */reader.readLine();
			pwd.setUsername(username);
			// Get the password
			System.out.print("Password? ");
			String password = /* "1981@prabhat"; */reader.readLine();
			pwd.setPassword(password);
			// Try the authentication
			int result = ssh.authenticate(pwd);
			// Evaluate the result
			if (result == AuthenticationProtocolState.COMPLETE) {
				// The connection is authenticated we can now do some real work!
				SessionChannelClient session = ssh.openSessionChannel();
				if (!session.requestPseudoTerminal("vt100", 80, 24, 0, 0, ""))
					System.out.println("Failed to allocate a pseudo terminal");
				if (session.startShell()) {
					IOStreamConnector input = new IOStreamConnector();
					IOStreamConnector output = new IOStreamConnector();
					IOStreamConnector error = new IOStreamConnector();
					output.setCloseOutput(false);
					input.setCloseInput(false);
					error.setCloseOutput(false);
					// ByteArrayInputStream bis = new ByteArrayInputStream(new
					// String("\n\n\n").getBytes());
					// input.connect(bis, session.getOutputStream());

					input.connect(pis, session.getOutputStream());

					// input.connect(System.in, session.getOutputStream());
					output.connect(session.getInputStream(), System.out);
					error.connect(session.getStderrInputStream(), System.out);
					// session.getOutputStream().write("\b".getBytes());
					// session.getOutputStream().write("\n".getBytes());

					// System.out.println("Waiting for request...");
					session.getState()
							.waitForState(ChannelState.CHANNEL_CLOSED);
				} else
					System.out.println("Failed to start the users shell");
				ssh.disconnect();
			} else {
				System.out.println("User/Password combination is incorrect");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public void verifyKey(VerifyEvent event) {
		// System.out.println("prabhatk: StyleTextTab.verifyKey()");
		if (event.keyCode == 8 || event.keyCode == 127) {
			if (cc.length == 0)
				event.doit = false;
		}
	}

}
